/*
 * Copyright (C) 2013 Daniel Wasilew <daniel.wasilew@codeminer.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.codeminer.parts.files;

import org.apache.commons.codec.digest.DigestUtils;

import java.io.*;
import java.util.LinkedList;
import java.util.List;

/**
 * User: Daniel Wasilew <daniel.wasilew@codeminer.org>
 * Date: 03.03.13
 * Time: 13:21
 */
public final class FileUtil {
    private FileUtil() {

    }

    public static void deleteFile(File file) {
        if (file.isDirectory()) {
            File[] child = file.listFiles();
            if (child != null) {
                for (File sub : child) {
                    deleteFile(sub);
                }
            }
            file.delete();
        } else {
            file.delete();
        }
    }

    public static void clearDirectory(File dir) {
        if (dir.isDirectory()) {
            File[] listFiles = dir.listFiles();
            if (listFiles != null) {
                for (File file : listFiles) {
                    deleteFile(file);
                }
            }
        }
    }

    public static void copyDirectory(File sourceLocation, File targetLocation) throws IOException {

        if (sourceLocation.isDirectory()) {
            if (!targetLocation.exists()) {
                targetLocation.mkdir();
            }

            String[] children = sourceLocation.list();
            for (String child : children) {
                copyDirectory(new File(sourceLocation, child),
                        new File(targetLocation, child));
            }
        } else {
            OutputStream out;
            try (InputStream in = new FileInputStream(sourceLocation)) {
                out = new FileOutputStream(targetLocation);
                byte[] buf = new byte[1024];
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
            }
            out.close();
        }
    }

    public static List<File> traverseDirectory(File directory, FileFilter fileFilter) {
        List<File> result = new LinkedList<>();

        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        result.addAll(traverseDirectory(file, fileFilter));
                    } else if (fileFilter.accept(file)) {
                        result.add(file);
                    }
                }
            }
        } else if (fileFilter.accept(directory)) {
            result.add(directory);
        }

        return result;
    }

    public static String calculateMD5Hash(File file) throws FileException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            return calculateMD5Hash(fis);
        } catch (IOException e) {
            throw new FileException(e);
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException ignored) {
                }
            }
        }
    }

    private static String calculateMD5Hash(InputStream fis) throws FileException {
        try {
            return DigestUtils.md5Hex(fis);
        } catch (IOException e) {
            throw new FileException(e);
        }
    }
}
